package com.platform.comm.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * Web I/O Util
 * @author libin
 */
@Slf4j
public abstract class WebIOUtil {

    /**
     * 将指定文件的内容复制到{@link HttpServletResponse}
     *
     * @see #copy(Path, HttpServletResponse, String)
     */
    public static void copy(File source, HttpServletResponse response, String contentType) throws IOException {
        copy(source.toPath(), response, contentType);
    }

    /**
     * 将指定路径的文件内容复制到{@link HttpServletResponse}。<br>
     * 并根据contentType参数设置Content-Type响应头
     *
     * @param contentType MIME类型
     * @throws IOException 读写文件异常
     */
    public static void copy(Path source, HttpServletResponse response, String contentType) throws IOException {
        log.debug("Copy all bytes from {} to ServletOutputStream...", source);
        Assert.isTrue(Files.isReadable(source), "The path does not exist or can't be read!");

        if (StringUtils.isNotEmpty(contentType)) {
            response.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
        }
        copyBytes(source, response);
    }

    /**
     * 将指定路径的文件内容复制到{@link HttpServletResponse}。<br>
     * 同时将设置Content-Disposition响应头为"<code>attachment; filename*=...</code>"以触发浏览器的另存为提示
     *
     * @param filename 下载提示的默认文件名
     * @throws IOException 获取{@link ServletOutputStream}异常
     */
    public static void download(Path source, HttpServletResponse response, String filename) throws IOException {
        log.debug("Download {}.... Original file name: {}", source, filename);
        Assert.isTrue(Files.isReadable(source), "This path does not exist or can not be read!");

        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''"
                + CommUtil.encodeURL(filename));
        copyBytes(source, response);
    }

    private static void copyBytes(Path source, HttpServletResponse response) {
        try (ServletOutputStream out = response.getOutputStream()) {
            Files.copy(source, out);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    public static void downloadFile(File file, HttpServletResponse response) throws IOException {
        log.debug("Download  Original file name: {}", file.getName());
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''"
                + CommUtil.encodeURL(file.getName()));
        FileInputStream fileInputStream = new FileInputStream(file);
        RestUtil.copy(fileInputStream, response.getOutputStream());
    }

    public static void downloadFile(String fileName, InputStream fileInputStream, HttpServletResponse response) throws IOException {
        log.debug("Download  Original file name: {}", fileName);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=utf-8''"
                + CommUtil.encodeURL(fileName));
        RestUtil.copy(fileInputStream, response.getOutputStream());
    }
}
